{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "dee3f82a-e9a4-400e-8ef3-d6942bffa909",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import pickle\n",
    "import numpy as np\n",
    "from collections import Counter\n",
    "from io import BytesIO\n",
    "import warnings\n",
    "\n",
    "warnings.filterwarnings(\"ignore\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ef009308-97ce-4001-a3bd-ffd70d416620",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "#将出行链数据转化成dataframe形式，用于作图\n",
    "class trip_data:\n",
    "    def __init__(self, trip_data):\n",
    "        self.GENERATED_TRIP = trip_data\n",
    "    def gen_df(self) :\n",
    "        l = len(self.GENERATED_TRIP)-1\n",
    "        data_time = []\n",
    "        for i in range(1, l):\n",
    "            x=self.GENERATED_TRIP[i][0].item()\n",
    "            data_time.append(x)\n",
    "        data_type = []\n",
    "        for i in range(1, l):\n",
    "            x=int(self.GENERATED_TRIP[i][3].item())\n",
    "            data_type.append(x)\n",
    "        data_lon = []\n",
    "        for i in range(1, l):\n",
    "            x=self.GENERATED_TRIP[i][1].item()\n",
    "            data_lon.append(x)\n",
    "        data_lat = [] \n",
    "        for i in range(1, l):\n",
    "            x=self.GENERATED_TRIP[i][2].item()\n",
    "            data_lat.append(x)\n",
    "        data={\n",
    "            'time': np.array(data_time),\n",
    "            'longitude': np.array(data_lon),\n",
    "            'latitude': np.array(data_lat),\n",
    "            'type': np.array(data_type)\n",
    "        }\n",
    "        df = pd.DataFrame(data)\n",
    "        return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "28b06a5b-117f-409e-bf12-7c9e51e66853",
   "metadata": {},
   "outputs": [],
   "source": [
    "#用于转换出行方式数据\n",
    "color_dict = {\n",
    "    99: '#FF0000',  # 红色\n",
    "    1: '#00FF00',  # 绿色\n",
    "    2: '#0000FF',  # 蓝色\n",
    "    3: '#FFA500',  # 橙色\n",
    "    4: '#800080'  # 紫色\n",
    "}\n",
    "type_dict = {1: \"WALK\",\n",
    "             2: \"VEHICLE\",\n",
    "             3: \"TRAIN\",\n",
    "             4: \"BICYCLE\",\n",
    "             99: \"STAY\"}\n",
    "\n",
    "#生成无地图的动态出行链\n",
    "class plot_travel_chain_no_osm:\n",
    "    def __init__(self, travel_data):\n",
    "        self.travel_data = travel_data\n",
    "\n",
    "    def gene_plot_data(self):\n",
    "        cut_index = list(self.travel_data[(self.travel_data['type'].diff() != 0)].index) + [len(self.travel_data)]\n",
    "        draw_data = []\n",
    "\n",
    "        for i in range(len(cut_index) - 1):\n",
    "            draw_data.append(self.travel_data.iloc[cut_index[i]:cut_index[i + 1], :])\n",
    "        return draw_data\n",
    "\n",
    "    def plot_travel_chain_no_osm(self, max_lim, min_lim):\n",
    "        x_max, y_max = max_lim\n",
    "        x_min, y_min = min_lim\n",
    "        fig, ax = plt.subplots()\n",
    "        ax.set_xlim(x_min, x_max)\n",
    "        ax.set_ylim(y_min, y_max)\n",
    "        writer = animation.PillowWriter(fps=15,\n",
    "                                metadata=dict(artist='Me'),\n",
    "                                bitrate=1800)\n",
    "        def animate(i):\n",
    "            for temp_data in self.gene_plot_data():\n",
    "                temp_type = temp_data.iloc[0, -1]\n",
    "                temp_color = color_dict[temp_type]\n",
    "                type_name = type_dict[temp_type]\n",
    "                plot_array = temp_data[['longitude', 'latitude']].to_numpy()\n",
    "                ax.plot(plot_array[:, 0], plot_array[:, 1], linewidth=3, label=type_name, c=temp_color, zorder=20)\n",
    "                ax.scatter(plot_array[:, 0][i], plot_array[:, 1][i], s=10, c='#800080',\n",
    "                           edgecolor='#800080', zorder=100)\n",
    "            return ax\n",
    "        handles, labels = ax.get_legend_handles_labels()\n",
    "        by_label = dict(zip(labels, handles))\n",
    "        ax.legend(by_label.values(), by_label.keys())\n",
    "        ani = animation.FuncAnimation(\n",
    "            fig, animate, frames=300, interval=100, blit=False, save_count=50)\n",
    "        return ani"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "9edef6b0-256c-482c-9190-dd4464723c35",
   "metadata": {},
   "outputs": [],
   "source": [
    "#在界面中展示gif\n",
    "from PIL import Image,ImageTk\n",
    "from PIL import ImageSequence\n",
    "import random\n",
    "import os,sys\n",
    "\n",
    "STR_FRAME_FILENAME=\"frame{}.png\"\n",
    "\n",
    "\n",
    "class playGif():\n",
    "    def __init__(self, file, temporary=\"\"):  # temporary 指临时目录路径，为空时则随机生成\n",
    "        self.__strPath = file\n",
    "        self.__index = 1  # 当前显示图片的帧数\n",
    "\n",
    "        if len(temporary) == 0:\n",
    "            self.strTemporaryFolder = self.crearteTemporaryFolder()  # 随机得到临时目录\n",
    "        else:\n",
    "            self.strTemporaryFolder = temporary  # 指定的临时目录\n",
    "\n",
    "        self.__intCount = 0  # gif 文件的帧数\n",
    "\n",
    "        self.decomposePics()  # 开始分解\n",
    "\n",
    "    def crearteTemporaryFolder(self):  # 生成临时目录名返回\n",
    "        # 获取当前调用模块主程序的运行目录\n",
    "        strSelfPath = str(os.path.dirname(os.path.realpath(sys.argv[0])))\n",
    "        if len(strSelfPath) == 0:\n",
    "            strSelfPath = os.path.join(os.getcwd())\n",
    "\n",
    "        def createRandomFolder(strSelfPath):  # 内嵌方法，生成随机目录用\n",
    "            length = random.randint(5, 10)  # 随机长度\n",
    "            path = \"\"\n",
    "            for i in range(length):\n",
    "                path = path + chr(random.randint(97, 122))  # 随机生成a-z字母\n",
    "\n",
    "            return os.path.join(strSelfPath, path)\n",
    "            #\n",
    "\n",
    "        # 获取当前软件目录\n",
    "\n",
    "        folder = createRandomFolder(strSelfPath)\n",
    "        while os.path.isdir(folder):  # 已存在\n",
    "            folder = createRandomFolder(strSelfPath)\n",
    "\n",
    "        return folder\n",
    "        #\n",
    "\n",
    "    def decomposePics(self):  # 分解 gif 文件的每一帧到独立的图片文件，存在临时目录中\n",
    "        i = 0\n",
    "        img = Image.open(self.__strPath)\n",
    "        self.__width, self.__height = img.size  # 得到图片的尺寸\n",
    "\n",
    "        os.mkdir(self.strTemporaryFolder)  # 创建临时目录\n",
    "        for frame in ImageSequence.Iterator(img):  # 遍历每帧图片\n",
    "            frame.save(os.path.join(self.strTemporaryFolder, STR_FRAME_FILENAME.format(i + 1)))  # 保存独立图片\n",
    "            i += 1\n",
    "\n",
    "        self.__intCount = i  # 得到 gif 的帧数\n",
    "        #\n",
    "\n",
    "    def getPicture(self, frame=0):  # 返回第 frame 帧的图片(width=0,height=0)\n",
    "        if frame == 0:\n",
    "            frame = self.__index\n",
    "        elif frame >= self.__intCount:\n",
    "            frame = self.__intCount  # 最后一张\n",
    "\n",
    "        img = tkinter.PhotoImage(file=os.path.join(self.strTemporaryFolder, STR_FRAME_FILENAME.format(frame)))\n",
    "        self.__index = self.getNextFrameIndex()\n",
    "\n",
    "        return img  # 返回图片\n",
    "\n",
    "\n",
    "\n",
    "    def getNextFrameIndex(self, frame=0):  # 返回下一张的帧数序号\n",
    "        if frame == 0:\n",
    "            frame = self.__index  # 按当前插入帧数\n",
    "\n",
    "        if frame == self.__intCount:\n",
    "            return 1  # 返回第1张，即从新开始播放\n",
    "        else:\n",
    "            return frame + 1  # 下一张\n",
    "        #\n",
    "\n",
    "    def playGif(self, tk, widget, time=100):  # 开始调用自身实现播放，time 单位为毫秒\n",
    "        img = self.getPicture()\n",
    "        widget.config(image=img)\n",
    "        widget.image = img\n",
    "        tk.after(time, self.playGif, tk, widget, time)  # 在 time 时间后调用自身\n",
    "\n",
    "        #\n",
    "\n",
    "    def close(self):  # 关闭动画文件，删除临时文件及目录\n",
    "        files = os.listdir(self.strTemporaryFolder)\n",
    "        for file in files:\n",
    "            os.remove(os.path.join(self.strTemporaryFolder, file))\n",
    "\n",
    "        os.rmdir(self.strTemporaryFolder)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e06f0b8-e337-4795-a198-5f18daa29229",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
